/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "UI_test.h"
#include "UI/实例部件/ui菜单.h"
#include "UI/intern/ui3D视口.h"

#include <随机数.h>



C_Widget* f_test_构建枚举组件(S_UI创建环境& ctx) {
	static S_Props p = f_alloc_EnumProp(nullptr, { {L"a", ""} }, L"枚举组件创建测试");
	return f_ui_创建枚举选择框(ctx, p, E_方向::e_纵向);
}

C_Widget* f_test_构建菜单项组件(S_UI创建环境& ctx) {
	C_菜单项* item = new C_菜单项(ctx, L"菜单项", "", 24);
	return item;
}


static S_Scene 测试场景;
C_Widget* f_test_构建3D视口组件(S_UI创建环境& ctx, S_设备环境& Ctx3D) {
	auto* w = (C_3D视口*)f_ui_创建3D视口(&测试场景, { 1024,1024 }, ctx, Ctx3D);
	//ctx.m_3DViewScene.push_back(w);

	return w;
}

C_Widget* f_test_行文本编辑框组件(S_UI创建环境& ctx) {
	auto w = f_ui_创建行文本编辑框(ctx);
	w->m_Size = { 256,256 };
	f_ui_set行文本框文本(w, L"text test");
	return w;
}

C_Widget* f_test_菜单组件(S_UI创建环境& ctx) {
	auto w = new C_菜单(E_方向::e_横向, ctx);
	w->m_TypeName = "主菜单";

	f_ui_添加菜单项(w,
		{
			(fp_on_菜单项点击)0, {
				{L"文件", "", 0},
			//	{L"编辑", "", 0},
			}
		}
		,
		ctx
		,
		0
	);

	return w;
}

C_Widget* f_test_Vec3组件(S_UI创建环境& ctx) {
	static S_Props vec = f_alloc_Vec3Prop(nullptr, L"vec test");
	auto w = f_ui_创建vec编辑框(ctx, vec);
	return w;
}

void f_test_VG变换内存(S_UI创建环境& ctx, uint32 num) {
	//std::vector<S_板载缓存*> bufs(num);
	for (uint32 j = 0; j < 50; ++j) {
		S_2D画布* s = f_surface_创建2D画布(nullptr, ctx.m_Ctx);


		f_surface_释放2D画布(s);
	}

}



void f_test_GPU缓存块操作(S_设备环境& m_Ctx) {
	/*S_板载缓存* buf = f_buf_create板载缓存(m_Ctx, E_板载缓存类型::e_SSBO, sizeof(vec2));

	uint32 num = 100;
	std::vector<S_GPU内存块索引> 内存块;
	内存块.reserve(num);

	for (uint32 i = 0; i < num; ++i) {
		auto 块 = f_buf_alloc(buf, 3);
		内存块.emplace_back(块);

		f_buf_Vec2_at(块, 0) = {float32(i), float32(i*0.01)};
		std::cout<< "内存分配 = " << 块.m_Mem.m_偏移 << " " << 块.m_Mem.m_大小 << std::endl;
	}

	for (uint32 i = 0; i < num; ++i) {
		vec2 val = f_buf_Vec2_at(内存块[i], 0);
		std::cout<< " p1 = " << val.x << " " << val.y << std::endl;
	}

	for (uint32 i = 0; i < num; ++i) {
		if (i & 1) {
			f_buf_erase(内存块[i]);
		}
	}

	for (uint32 i = 0; i < num; ++i) {
		if (i & 1) {
			vec2 val = f_buf_Vec2_at(内存块[i], 0);
			std::cout << " p2 = " << val.x << " " << val.y << std::endl;
		}
		auto 块 = f_buf_alloc(buf, 3);
		内存块.emplace_back(块);
	}

	f_buf_release板载缓存(buf);*/


	auto* 顶点 = f_buf_create板载缓存(m_Ctx, E_板载缓存类型::e_VBO, E_板载缓存类型::e_VBO|E_板载缓存类型::e_SSBO , sizeof(S_2D图元顶点), 1);

	//std::vector<S_GPU偏移大小> 内存块;
	std::vector<S_GPU内存块索引> 内存块;
	std::mutex tem锁;


#pragma omp parallel for
	for (int32 i = 0; i < 1000; ++i) {
		uint32 bufNum = f_get随机UIntRange(0, 3);

		switch (bufNum)
		{
		case 0: 
		case 1: {
			uint32 id = f_get随机UIntRange(0, 内存块.size());

			if (bufNum) {
				S_GPU内存块索引 要移除的块{};
				tem锁.lock();
				if (id < 内存块.size()) {
					要移除的块 = 内存块[id];
					内存块.erase(内存块.begin() + id);
				}
				tem锁.unlock();

				if (要移除的块.m_Buf) {
					f_buf_erase(要移除的块);
				}
			}
			else {
				tem锁.lock();
				if (id < 内存块.size()) {
					S_GPU内存块索引 要重置的块 = 内存块[id];
					f_buf_gresize(要重置的块, f_get随机UIntRange(20, 100000));
				}
				tem锁.unlock();
			}

			break;
		}
			
		default: {
			auto 块 = f_buf_alloc(顶点, f_get随机UIntRange(20, 100000));

			tem锁.lock();
			内存块.push_back(块);
			tem锁.unlock();
			break;
		}
			
		}
		


	}


#pragma omp parallel for
	for (int32 i = 0; i < 100; ++i) {
		auto 块 = f_buf_alloc(顶点, f_get随机UIntRange(20, 100000));

		tem锁.lock();
		内存块.push_back(块);
		tem锁.unlock();

		uint32 num = f_get随机UIntRange(1, 100);
#pragma omp parallel for
		for (int32 j = 0; j < num; ++j) {
			
			if (块.m_Buf) {
				uint32 k = f_get随机UIntRange(20, 100000);
				if (k & 1) {
					uint32 bufNum = f_get随机UIntRange(20, 100000);
					f_buf_gresize(块, bufNum);
				}
				else {
					uint32 bufNum = f_get随机UIntRange(0, 内存块.size());
					if (bufNum < 内存块.size()) {
						tem锁.lock();
						//auto 新块 = 内存块[bufNum];
						f_buf_erase(内存块[bufNum]);
						内存块[bufNum] = f_buf_alloc(顶点, f_get随机UIntRange(0, 100000));
						tem锁.unlock();

					}
				}
			}
			else {
				块 = f_buf_alloc(顶点, f_get随机UIntRange(0, 100000));
				tem锁.lock();
				内存块.push_back(块);
				tem锁.unlock();
			}
		}

		std::cout<<i<<std::endl;
	}




	/*std::vector<uint8> 内存遮罩测试;
	for (auto& e : 内存块) {
		uint64 num = e.m_偏移 + e.m_大小;
		if (num > 内存遮罩测试.size()) {
			内存遮罩测试.resize(num);
		}
		for (uint64 i = 0; i < e.m_大小; ++i) {
			内存遮罩测试[i + e.m_偏移] = 0xff;
		}
	}
	uint64 num = 内存遮罩测试.size();
	auto* p = 内存遮罩测试.data();
	for (uint64 i = 0; i < num; ++i) {
		if (p[i] != 0xff) {
			//std::cout<<i<<std::endl;
		}
	}*/

	auto p = 顶点->m_分配器.m_内存回收偏移.data();
	auto num = 顶点->m_分配器.m_内存回收偏移.size();
	std::set<uint32> tem;
	for (uint32 i = 0; i < num; ++i) {
		if (tem.find(p[i].m_偏移) == tem.end()) {
			tem.insert(p[i].m_偏移);
		}
		else {
			std::cout<<i<<std::endl;
		}
	}
	
	f_buf_release板载缓存(顶点);
}

void f_test_ArrayInsert() {
	S_F32Array* a = (S_F32Array*)f_core_array_new(0, sizeof(float32));

	for (uint32 i = 0; i < 3000; ++i) {
		uint32 num = f_get随机UIntRange(1, 100000);
		S_F32Array* b = (S_F32Array*)f_core_array_new(num, sizeof(float32));

		uint64 插入位置 = f_get随机UIntRange(0, 100000000000);
		f_core_array_insert((S_Array*)a, (S_Array*)b, 插入位置);

		f_core_array_free((S_Array*)b);
		std::cout<<i<<std::endl;
	}
	
	f_core_array_free((S_Array*)a);
}



/*for (int32 size = 2; size < 512; size <<= 1) {
	//for (int32 size = 2; size < 512; size <<= 1) {
	//Bitonic merge

	for (uint32 stride = size / 2; stride > 0; stride >>= 1) {
		if (a[stride] > a[size]) {
			auto t = a[stride];
			a[stride] = a[size];
			a[size] = t;
		}

		std::cout << "stride = " << stride << " : " << size << std::endl;
	}
}*/



/*#pragma loop(hint_parallel(0))
for (int32 size = 0; size < 400000000; ++size) {
	for (uint32 stride = size / 2; stride > 0; stride >>= 1) {
	}
	std::cout << "stride = " << size << " : " << size << std::endl;
}*/



/*vec2 a = vec2{float32(size - i), float32(size - 2)} *vec2{float32(size + i), float32(size + 2)};
			vec2 b = vec2{ float32(size - i), float32(size - 2) } / vec2{ float32(size + i), float32(size + 2) };
			vec2 c = a / b;
			X86 = a * c;
			X86 = X86 / c;*/

	/*static float64 gdur;
	static clock_t g时间start = clock();
	static clock_t g时间end;
	gdur = 0;
	for (uint32 i = 0; i < 100; ++i) {
		g时间end = clock();
		vec3 X86 = {};
		auto mat = f_mat44_identity();
		for (uint64 size = 0; size < 400000000; ++size) {
			vec3 v; v.x = i; v.y = i * size; v.z = i + 1;
			X86 = mat * v;
			v = mat * X86;
			X86 = mat * v;
		}
		g时间start = clock();
		auto t = (g时间start - g时间end);
		gdur += t;
		std::cout << "stride = " << (g时间start - g时间end) << " " << X86.x << " " << X86.y << std::endl;
		//std::cout << "stride = " << (g时间start - g时间end) * 1000 / CLOCKS_PER_SEC << std::endl;
	}
	std::cout << "X86 VS SSE = " << gdur / 100 << std::endl;*/

	//=== VEC2 ===
	// X86 154.39
	// SSE 1507
	// 
	// === MAT44 ===
	// X86 = 158.87
	// SSE = 1201.1
	// 





